package ecommerce.factory.dao.mysql;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.util.ArrayList;

import java.util.HashMap;

import ecommerce.exception.EcommerceException;
import ecommerce.factory.interfaces.ProductoDAO;
import ecommerce.to.CategoriaTO;
import ecommerce.to.ProductoTO;
import ecommerce.util.ConexionBD;
import ecommerce.util.EcommerceLog;

public class MySQLProductoDAO implements ProductoDAO {
    public MySQLProductoDAO() {
    }

    public void crear(ProductoTO entidad) throws EcommerceException {
    
        //JDBC otras alternativas es usar JPA, Spring JDBC,  Hibernate, iBatis
        Connection cn = null;
        CallableStatement cstm = null;
        String sql;
        try{
            cn = ConexionBD.getInstance().getConexionBD();
            sql = "{call sp_producto_insertar(?, ?, ?, ?, ?)}";
            cstm = cn.prepareCall(sql);
            cstm.setString(1, entidad.getNombre());
            cstm.setFloat(2, entidad.getPrecio());
            cstm.setInt(3, entidad.getStock());
            cstm.setInt(4, entidad.getCategoriaTO().getId());
            cstm.setBytes(5, entidad.getImagen());
            
            // 0 no se inserto
            if(cstm.executeUpdate() ==0) {
                throw new EcommerceException("No se pudo insertar");
            }
            
        }catch(EcommerceException e){
            EcommerceLog.error(e);
            throw e;
        }catch(Exception e){
            EcommerceLog.error(e);
            throw new EcommerceException("Error al crear el producto");
        }finally{
            ConexionBD.getInstance().close(cstm);
            ConexionBD.getInstance().close(cn);
        }
    
    }

    public void modificar(ProductoTO entidad) throws EcommerceException {
    
        //JDBC otras alternativas es usar JPA, Spring JDBC,  Hibernate, iBatis
        Connection cn = null;
        CallableStatement cstm = null;
        String sql;
        try{
            cn = ConexionBD.getInstance().getConexionBD();
            sql = "{call sp_producto_modificar(?, ?, ?, ?, ?, ?)}";
            cstm = cn.prepareCall(sql);
            cstm.setInt(1, entidad.getId());
            cstm.setString(2, entidad.getNombre());
            cstm.setFloat(3, entidad.getPrecio());
            cstm.setInt(4, entidad.getStock());
            cstm.setInt(5, entidad.getCategoriaTO().getId());
            cstm.setBytes(6, entidad.getImagen());
            
            // 0 no se inserto
            if(cstm.executeUpdate() ==0) {
                throw new EcommerceException("No se pudo modificar");
            }
            
        }catch(EcommerceException e){
            EcommerceLog.error(e);
            throw e;
        }catch(Exception e){
            EcommerceLog.error(e);
            throw new EcommerceException("Error al modificar el producto");
        }finally{
            ConexionBD.getInstance().close(cstm);
            ConexionBD.getInstance().close(cn);
        }
    
    }

    public void eliminar(int id) throws EcommerceException {
    
        //JDBC otras alternativas es usar JPA, Spring JDBC,  Hibernate, iBatis
        Connection cn = null;
        CallableStatement cstm = null;
        String sql;
        try{
            cn = ConexionBD.getInstance().getConexionBD();
            sql = "{call sp_producto_eliminar(?)}";
            cstm = cn.prepareCall(sql);
            cstm.setInt(1, id);
            
            // 0 no se eliminar
            if(cstm.executeUpdate() ==0) {
                throw new EcommerceException("No se pudo eliminar");
            }
            
        }catch(EcommerceException e){
            EcommerceLog.error(e);
            throw e;
        }catch(Exception e){
            EcommerceLog.error(e);
            throw new EcommerceException("Error al eliminar el producto");
        }finally{
            ConexionBD.getInstance().close(cstm);
            ConexionBD.getInstance().close(cn);
        }
    
    }

    public ArrayList<ProductoTO> traerTodo() throws EcommerceException{
        return null;
    }

    public ProductoTO traerPorId(int id) throws EcommerceException {
        Connection cn = null;
        CallableStatement cstm = null;
        ResultSet rs = null;
        ProductoTO proTO = new ProductoTO();
        String sql;
        try{
            cn = ConexionBD.getInstance().getConexionBD();
            sql = "{call sp_producto_traer_por_id(?)}";
            cstm = cn.prepareCall(sql);
            cstm.setInt(1,id);
            
            rs = cstm.executeQuery();
            while(rs.next()) {              
                proTO.setId(rs.getInt("pro_id"));
                proTO.setNombre(rs.getString("pro_nom"));
                proTO.setPrecio(rs.getFloat("pro_precio"));
                proTO.setStock(rs.getInt("pro_stock"));
                proTO.setImagen(rs.getBytes("pro_imagen"));
                proTO.setCategoriaTO(new CategoriaTO(rs.getInt("cat_id"), rs.getString("cat_nom"),null));
            }
        }catch(EcommerceException e){
            EcommerceLog.error(e);
            throw e;
        }catch(Exception e){
            EcommerceLog.error(e);
            throw new EcommerceException("Error al traer los productos");
        }finally{
            ConexionBD.getInstance().close(rs);
            ConexionBD.getInstance().close(cstm);
            ConexionBD.getInstance().close(cn);
        }
        
        return proTO;
    }
    
    public ArrayList<ProductoTO> traerPorNombre(String nombre) throws EcommerceException{
        //JDBC otras alternativas es usar JPA, Spring JDBC,  Hibernate, iBatis
        Connection cn = null;
        CallableStatement cstm = null;
        ResultSet rs = null;
        ArrayList<ProductoTO> arrProTO = new ArrayList<ProductoTO>();
        String sql;
        try{
            cn = ConexionBD.getInstance().getConexionBD();
            sql = "{call sp_producto_traer_por_nombre(?)}";
            cstm = cn.prepareCall(sql);
            cstm.setString(1,nombre);
            
            rs = cstm.executeQuery();
            while(rs.next()) {
                ProductoTO proTO = new ProductoTO();
                proTO.setId(rs.getInt("pro_id"));
                proTO.setNombre(rs.getString("pro_nom"));
                proTO.setPrecio(rs.getFloat("pro_precio"));
                proTO.setStock(rs.getInt("pro_stock"));
                proTO.setImagen(rs.getBytes("pro_imagen"));
                proTO.setCategoriaTO(new CategoriaTO(rs.getInt("cat_id"), rs.getString("cat_nom"),null));
                
                arrProTO.add(proTO);
            }
        }catch(EcommerceException e){
            EcommerceLog.error(e);
            throw e;
        }catch(Exception e){
            EcommerceLog.error(e);
            throw new EcommerceException("Error al traer los productos");
        }finally{
            ConexionBD.getInstance().close(rs);
            ConexionBD.getInstance().close(cstm);
            ConexionBD.getInstance().close(cn);
        }
        
        return arrProTO;
    }
    
    public HashMap traerDatosGrafica1() throws EcommerceException{
        Connection cn = null;
        CallableStatement cstm = null;
        ResultSet rs = null;
        HashMap datos = new HashMap();
        String sql;
        try{
            cn = ConexionBD.getInstance().getConexionBD();
            sql = "{call sp_grafica1()}";
            cstm = cn.prepareCall(sql);
            
            rs = cstm.executeQuery();
            while(rs.next()) {                
                datos.put(rs.getString("categoria"),rs.getInt("cantidad"));
            }
        }catch(EcommerceException e){
            EcommerceLog.error(e);
            throw e;
        }catch(Exception e){
            EcommerceLog.error(e);
            throw new EcommerceException("Error al traer datos para el Grafico");
        }finally{
            ConexionBD.getInstance().close(rs);
            ConexionBD.getInstance().close(cstm);
            ConexionBD.getInstance().close(cn);
        }
        
        return datos;
    }
}
